Design system.
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

250 lines
7.1 KiB

  1. import type {GetStaticPaths, GetStaticProps, NextPage} from 'next';
  2. import * as fs from 'fs/promises';
  3. import * as path from 'path';
  4. import * as React from 'react'
  5. import {useRouter} from 'next/router';
  6. import ReactMarkdown from 'react-markdown';
  7. import {DocsLayout, Page} from '@/components/DocsLayout';
  8. export interface Props {
  9. componentPages: { name: string; components: Page[] }[],
  10. docsPages: Page[],
  11. examplePages: Page[],
  12. markdown: string,
  13. }
  14. const InnerPage: NextPage<Props> = ({
  15. componentPages,
  16. examplePages,
  17. docsPages,
  18. markdown,
  19. }) => {
  20. const router = useRouter();
  21. const sidebarOpen = router.query.open === 'sidebar';
  22. return (
  23. <DocsLayout
  24. componentPages={componentPages}
  25. examplePages={examplePages}
  26. docsPages={docsPages}
  27. sidebarOpen={sidebarOpen}
  28. >
  29. {markdown && (
  30. <ReactMarkdown
  31. className="my-12 leading-loose"
  32. components={{
  33. ul: ({node, ordered: _ordered, ...props}) => (
  34. <ul
  35. {...props}
  36. className="list-disc pl-4"
  37. />
  38. ),
  39. li: ({node, ...props}) => (
  40. <li
  41. {...props}
  42. className="list-item pl-4"
  43. />
  44. ),
  45. }}
  46. >
  47. {markdown}
  48. </ReactMarkdown>
  49. )}
  50. <pre>
  51. <code>
  52. {JSON.stringify(componentPages, null, 2)}
  53. </code>
  54. </pre>
  55. </DocsLayout>
  56. )
  57. }
  58. export const getStaticProps: GetStaticProps = async (ctx) => {
  59. const { params } = ctx;
  60. const { url } = params as { url: string[] };
  61. const [platform, framework, ...etcUrl] = url;
  62. const props = {} as Record<string, unknown>;
  63. const docsPath = path.resolve('../../docs');
  64. const docs = await fs.readdir(docsPath);
  65. props.docsPages = docs.map((d) => ({
  66. id: d,
  67. href: `/docs/${d}`,
  68. label: d
  69. .split('-')
  70. .slice(1)
  71. .map((dd) => dd.slice(0, 1).toUpperCase() + dd.slice(1))
  72. .join(' ')
  73. .replace(/\.md/i, '')
  74. }));
  75. // const categoriesPath = path.resolve('../../categories');
  76. // const categories = await fs.readdir(categoriesPath);
  77. // props.componentPages = categories.map((c) => ({
  78. // id: c,
  79. // href: `/categories/${c}`,
  80. // label: c.split('-').map((cc) => cc.slice(0, 1).toUpperCase() + cc.slice(1)).join(' '),
  81. // }));
  82. // const pagesPath = path.resolve('src/pages');
  83. // const examplesPath = path.resolve(pagesPath, 'examples');
  84. // const examplesRaw = await fs.readdir(examplesPath);
  85. // const examplesIndexPage = await Promise.all(
  86. // examplesRaw.map(async (c) => {
  87. // const indexPath = await path.resolve(examplesPath, c, 'index.tsx');
  88. // try {
  89. // const statResult = await fs.stat(indexPath);
  90. // return [c, statResult.isFile()];
  91. // } catch {
  92. // // noop
  93. // }
  94. //
  95. // return [c, false];
  96. // })
  97. // ) as [string, boolean][];
  98. // const examples = examplesIndexPage
  99. // .filter(([, hasIndexPage]) => hasIndexPage)
  100. // .map(([key]) => key);
  101. // props.examplePages = examples.map((e) => ({
  102. // id: e,
  103. // href: `/examples/${e}`,
  104. // label: e.split('-').map((ee) => ee.slice(0, 1).toUpperCase() + ee.slice(1)).join(' '),
  105. // }));
  106. const isHome = !Array.isArray(params.url);
  107. if (isHome) {
  108. const readmePath = path.resolve('../../README.md');
  109. props.markdown = await fs.readFile(readmePath, 'utf-8');
  110. }
  111. const theParamsUrl = params.url as string[];
  112. const isDocs = Array.isArray(theParamsUrl) && theParamsUrl[0] === 'docs';
  113. if (isDocs) {
  114. const docsPath = path.resolve('../../docs', theParamsUrl[1] as string);
  115. props.markdown = await fs.readFile(docsPath, 'utf-8');
  116. }
  117. const typedocData = await fs.readFile('typedoc.data.json', 'utf-8');
  118. const project = JSON.parse(typedocData) as any;
  119. props.componentPages = project.children.reduce(
  120. (theComponents, pkg) => {
  121. const packageNameFragments = pkg.name.split('-');
  122. const packageFramework = packageNameFragments.pop();
  123. const categoryBaseName = packageNameFragments.pop();
  124. console.log(packageFramework, categoryBaseName);
  125. if (theComponents.some((c) => c.name === categoryBaseName)) {
  126. return theComponents.map((cc) => {
  127. if (cc.name !== categoryBaseName) {
  128. return cc;
  129. }
  130. let components = [];
  131. if (packageFramework === 'react') {
  132. components = pkg.children
  133. .filter((exported) => {
  134. return exported.kind === 64; // Function, these are react components
  135. })
  136. .map((component) => {
  137. return {
  138. ...component,
  139. id: component.name,
  140. href: `/categories/${categoryBaseName}/${component.name}`,
  141. label: component.name,
  142. descriptionMarkdown: component.signatures[0].comment.summary.reduce(
  143. (theText, t) => {
  144. if (t.kind === 'text') {
  145. return `${theText}${t.text}`;
  146. }
  147. if (t.kind === 'inline-tag' && t.tag === '@link') {
  148. return `${theText}[${t.text}](#)` // TODO set URL
  149. }
  150. return theText;
  151. },
  152. ''
  153. ),
  154. };
  155. });
  156. }
  157. return {
  158. ...cc,
  159. name: categoryBaseName,
  160. packages: {
  161. ...(cc.packages ?? {}),
  162. [packageFramework]: {
  163. components,
  164. },
  165. },
  166. };
  167. })
  168. }
  169. let components = [];
  170. if (packageFramework === 'react') {
  171. components = pkg.children
  172. .filter((exported) => {
  173. return exported.kind === 64; // Function, these are react components
  174. })
  175. .map((component) => {
  176. return {
  177. ...component,
  178. id: component.name,
  179. href: `/categories/${categoryBaseName}/${component.name}`,
  180. label: component.name,
  181. descriptionMarkdown: component.signatures[0].comment.summary.reduce(
  182. (theText, t) => {
  183. if (t.kind === 'text') {
  184. return `${theText}${t.text}`;
  185. }
  186. if (t.kind === 'inline-tag' && t.tag === '@link') {
  187. return `${theText}[${t.text}](#)` // TODO set URL
  188. }
  189. return theText;
  190. },
  191. ''
  192. ),
  193. };
  194. });
  195. }
  196. return [
  197. ...theComponents,
  198. {
  199. name: categoryBaseName,
  200. packages: {
  201. [packageFramework]: {
  202. components,
  203. }
  204. }
  205. }
  206. ]
  207. },
  208. [],
  209. );
  210. return {
  211. props,
  212. };
  213. };
  214. export default InnerPage;
  215. export const getStaticPaths: GetStaticPaths = async () => {
  216. const docsPath = path.resolve('../../docs');
  217. const docs = await fs.readdir(docsPath);
  218. const categoriesPath = path.resolve('../../categories');
  219. const categories = await fs.readdir(categoriesPath);
  220. return {
  221. paths: [
  222. ...docs.map((d) => `/docs/${d}`),
  223. ],
  224. fallback: true,
  225. };
  226. };